#include <thread>
#include <queue>
#include <functional>
#include <iostream>

#include "condition.h"
#include "mutex.h"

class threadPool
{
    using Functor = std::function<void()>;
    private:
        std::queue<Functor> taskQueue;
        std::vector<std::thread> threadArry;
        utils::MutexLock mutex;
        utils::Condition condition;
        int threadNumber;
    private:
        void work()
        {
            Functor task;
            while (true)
            {
                {
                    utils::MutexLockGuard guard(mutex);
                    while (taskQueue.empty())
                    {
                        condition.Wait();
                    }
                    task = taskQueue.front(); taskQueue.pop();
                }
                task();
            }
        }
    public:
        explicit threadPool(int num) : condition(mutex)
        {
            threadNumber = num;
        }
        ~threadPool()
        {
            for (auto& thread : threadArry)
            {
                if (thread.joinable())
                {
                    thread.join();
                }
            }
        }
        void Run()
        {
            for (int i = 0; i < threadNumber; i++)
            {
                threadArry.push_back(std::thread(&threadPool::work, this));
            }
        }
        void ConsumeTask(Functor task)
        {
            {
                 utils::MutexLockGuard guard(mutex);
                 taskQueue.push(task);
            }
           condition.Notify();
        }
};

int main()
{
    threadPool pool(3);
    pool.Run();
    for (int i = 0; i < 10; i++) {
      pool.ConsumeTask(std::bind([](int num) {
        std::cout << num << std::endl;
      }, i));
    }
   
    return 0;
}